from urllib.parse import urlencode, parse_qs
from urllib.request import urlopen

from django.shortcuts import render

# Create your views here
from rest_framework import request
from rest_framework import status
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework_jwt.settings import api_settings

from carts.utils import merge_cart_cookie_to_redis
from mall import settings
from oauth.models import OAuthQQUser
from oauth.serializers import QQRegisterSerializer
from oauth.utils import OauthQQ

# 获取url和code
from utils.exceptions import logger


class QQAuthURLView(APIView):
    """
    实现出现QQ授权登录视图
    GET /oauth/qq/statues/
    """

    def get(self, request):
        # 生成auth_url
        # https://graph.qq.com/oauth2.0/authorize
        # 请求参数请包含如下内容：
        # response_type   必须      授权类型，此值固定为“code”。
        # client_id       必须      申请QQ登录成功后，分配给应用的appid。(配置文件里)
        # redirect_uri    必须      成功授权后的回调地址，必须是注册appid时填写的主域名下的地址，建议设置为网站首页或网站的用户中心。注意需要将url进行URLEncode。
        # state           必须      client端的状态值。用于第三方应用防止CSRF攻击，成功授权后回调时会原样带回。请务必严格按照流程检查用户与state参数状态的绑定。
        # scope              可选      scope=get_user_info

        # 获取state
        state = request.query_params.get('state')

        # # 设置base_url,需要添加 ?
        # base_url = 'https://graph.qq.com/oauth2.0/authorize?'
        # # 组织参数
        # params = {
        #     'response_type': 'code',
        #     'client_id': settings.QQ_APP_ID,
        #     'redirect_uri': settings.QQ_REDIRECT_URL,
        #     'state': state,
        # }
        # # 对参数进行urlencode,然后拼接auth_url
        # auth_url=base_url+urlencode(params)


        # 提取代码后
        qq = OauthQQ()
        auth_url = qq.get_oauth_url(state)

        # 返回响应
        return Response({'auth_url': auth_url})


# 根据code获取token
class QQTokenView(GenericAPIView):
    """
   获取access_token
   GET /oauth/qq/users/?code=xxx
   """
    serializer_class = QQRegisterSerializer

    def get(self, request):
        # PC网站：https://graph.qq.com/oauth2.0/token
        # GET
        # grant_type      必须      授权类型，在本步骤中，此值为“authorization_code”。
        # client_id       必须      申请QQ登录成功后，分配给网站的appid。
        # client_secret   必须      申请QQ登录成功后，分配给网站的appkey。
        # code            必须      上一步返回的authorization
        # redirect_uri    必须      与上面一步中传入的redirect_uri保持一致。

        # 获取code
        code = request.query_params.get('code')

        # # 设置base_url
        # base_url = 'https://graph.qq.com/oauth2.0/token?'
        # # 组织参数
        # params = {
        #     'grant_type': 'authorization_code',
        #     'client_id': settings.QQ_APP_ID,
        #     'client_secret': settings.QQ_APP_KEY,
        #     'redirect_uri': settings.QQ_REDIRECT_URL,
        #     'code': code
        # }
        # # 对参数进行urlencode,然后拼接url
        # url = base_url + urlencode(params)
        #
        # # 服务器向QQ服务器发送请求,获取响应
        # response = urlopen(url)
        #
        # # 读取数据
        # # data是由二进制数据转化成字符串
        # data = response.read().decode()
        # # 将字符串类型转成字典
        # query_params = parse_qs(data)
        #
        # # 获取token
        # access_token = query_params.get('access_token')
        # # access_token是一个列表
        #
        # # 判断是否有access_token
        # if access_token is None:
        #     raise Exception('获取token失败')
        #
        # return access_token[0]

        ##提取代码
        qq = OauthQQ()
        try:
            access_token = qq.get_access_token(code)
            openid = qq.get_openid(access_token)
        except Exception as e:
            logger.error(e)
            return Response({'message': '服务异常'}, status=status.HTTP_503_SERVICE_UNAVAILABLE)

        ## 通过openid判断用户是否存在
        try:
            qq_user = OAuthQQUser.objects.get(openid=openid)
        except OAuthQQUser.DoesNotExist:
            # 不存在就是第一次授权登录
            token = OAuthQQUser.generate_save_user_token(openid)
            return Response({'access_token': token})
        else:
            # 不是第一次登陆,查询用户,生成登陆token
            user = qq_user.user
            jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
            jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

            payload = jwt_payload_handler(user)
            token = jwt_encode_handler(payload)
            response = Response({
                'token': token,
                'user_id': user.id,
                'user_name': user.username
            })

            response = merge_cart_cookie_to_redis(request, user, response)
        return response

    def post(self, request):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = serializer.save()

        # 生成已经登陆的token
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)

        response = Response({
            'token': token,
            'user_id': user.id,
            'username': user.username
        })

        response = merge_cart_cookie_to_redis(request, user, response)
        return response
